package org.xxpay.pay.channel.adapay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.service.schema.util.StringUtil;
import com.huifu.adapay.Adapay;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import com.huifu.adapay.model.MerConfig;
import com.huifu.adapay.model.Payment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.domain.api.AbstractRes;
import org.xxpay.core.common.domain.api.ApiBuilder;
import org.xxpay.core.common.domain.api.PayRes;
import org.xxpay.core.common.util.AmountUtil;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayment;
import org.xxpay.pay.channel.swiftpay.SwiftpayPaymentService;
import org.xxpay.pay.mq.BaseNotify4MchPay;
import org.xxpay.pay.mq.Mq4PayQuery;
import org.xxpay.pay.mq.queue.MqQueue4Statistics;
import java.util.*;

/**
 * @author: kk
 * @date: 18/3/1
 * @description: 汇付天下支付接口
 */
@Service
public class AdapayPaymentService extends BasePayment {

    @Autowired
    private Mq4PayQuery mq4PayQuery;

    @Autowired
    public BaseNotify4MchPay baseNotify4MchPay;

    @Autowired
    public MqQueue4Statistics mqQueue4Statistics;

    private static final MyLog _log = MyLog.getLog(SwiftpayPaymentService.class);

    @Override
    public String getChannelName() {
        return PayConstant.CHANNEL_NAME_SWIFTPAY;
    }

    /**
     * 支付
     *
     * @param payOrder
     * @return
     */
    @Override
    public AbstractRes pay(PayOrder payOrder) {
        String channelId = payOrder.getChannelId();
        AbstractRes retObj;
        switch (channelId) {
            case PayConstant.PAY_CHANNEL_ADAPAY_WXPAY_PUB:
                retObj = executePayment(payOrder, payOrder.getChannelUser(), "wx_pub");
                break;
            case PayConstant.PAY_CHANNEL_ADAPAY_ALIPAY_QR:
                retObj = executePayment(payOrder, null, "alipay_qr");
                break;
            case PayConstant.PAY_CHANNEL_ADAPAY_ALIPAY_WAP:
                retObj = executePayment(payOrder, null, "alipay_wap");
                break;
            default:
                return ApiBuilder.bizError("不支持的支付宝渠道[channelId=" + channelId + "]");
        }
        return retObj;
    }

    /**
     * 执行一个支付交易
     *
     * @return 创建的支付对象
     * @throws Exception 异常
     */
    public AbstractRes executePayment(PayOrder payOrder, String openid, String channel) {
        String str = getPayParam(payOrder);

        PayRes retObj = ApiBuilder.buildSuccess(PayRes.class);
        JSONObject object = JSONObject.parseObject(str);
        /**
         * debug 模式，开启后有详细的日志
         */
        Adapay.debug = true;

        /**
         * prodMode 模式，默认为生产模式，false可以使用mock模式
         */
        Adapay.prodMode = true;

        /**
         * 初始化商户配置，服务器启动前，必须通过该方式初始化商户配置完成
         * apiKey为prod模式的API KEY
         * mockApiKey为mock模式的API KEY
         * rsaPrivateKey为商户发起请求时，用于请求参数加签所需要的RSA私钥
         */


        MerConfig merConfig = new MerConfig();
        merConfig.setApiKey(object.getString("apiKey"));
        merConfig.setApiMockKey(object.getString("mockApiKey"));
        merConfig.setRSAPrivateKey(object.getString("rsaPrivateKey"));
        try {
            Adapay.initWithMerConfig(merConfig);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //创建支付对象的参数，全部参数请参考 https://docs.adapay.tech/api/index.html
        Map<String, Object> paymentParams = new HashMap<>(10);

        // 设置超时时间 单位毫秒 类型 int
        // adapay_connection_request_timeout 类型 int, 单位：毫秒 ms
        // 非必须, 默认 10000 指从连接池获取连接的 timeout
        //paymentParams.put("adapay_connection_request_timeout", 1500);
        // adapay_connect_timeout 单位：毫秒 ms
        // 非必须, 默认 30000 指客户端和服务器建立连接的timeout
        //paymentParams.put("adapay_connect_timeout", 1500);
        // adapay_socket_timeout 单位：毫秒 ms
        // 非必须, 默认 30000 指客户端从服务器读取数据的timeout，超出后会抛出SocketTimeOutException
        //paymentParams.put("adapay_socket_timeout", 1500);

        // 设置网络区域
        // 非必须, 默认 shanghai, 如果要使用其他区域请提交工单备注服务器公网出口IP地址申请开通（如：beijing）
        //paymentParams.put("adapay_region", "beijing");


        paymentParams.put("app_id", object.getString("appId"));
        paymentParams.put("order_no", payOrder.getPayOrderId());

        paymentParams.put("pay_amt", AmountUtil.convertCent2Dollar(payOrder.getAmount() + ""));

        if (!StringUtil.isEmpty(openid)) {
            paymentParams.put("pay_channel", channel);

            Map<String, Object> expend = new HashMap<>();
            expend.put("open_id", openid);
            paymentParams.put("expend", expend);
        } else {
            paymentParams.put("pay_channel", channel);
        }

        paymentParams.put("goods_title", payOrder.getBody());
        paymentParams.put("goods_desc", payOrder.getSubject());

        paymentParams.put("div_members", "");


        //调用sdk方法，创建支付，得到支付对象
        Map<String, Object> payment = new HashMap<>();
        try {
            _log.info("支付交易，请求参数：" + JSON.toJSONString(paymentParams));
            payment = Payment.create(paymentParams);
            _log.info("支付交易，返回参数：" + JSON.toJSONString(payment));
            Map<String, Object> expend = (Map<String, Object>) payment.get("expend");
            if (expend == null) {
                return ApiBuilder.bizError("请求渠道支付异常");
            }
            if (!StringUtil.isEmpty(openid)) {
                retObj.setAppInfo(PayConstant.PAY_METHOD_WX_JSAPI, JSONObject.parseObject(expend.get("pay_info") + ""));
            } else if ("alipay_wap".equals(channel)) {
                retObj.setPayUrl(expend.get("pay_info") + "");
            } else if ("alipay_qr".equals(channel)) {
                retObj.setPayUrl(expend.get("qrcode_url") + "");
            }
            retObj.setPayOrderId(payOrder.getPayOrderId()); //支付成功
            return retObj;
        } catch (BaseAdaPayException e) {
            return ApiBuilder.bizError("操作失败!" + e.getMessage());
        }
    }

}
